﻿#include<iostream>
using std::cin;
using std::cout; 
using std::endl;

////C语言中，交换不同类型的数值
//void Swap(int& left, int& right)
//{
//	int temp = left;
//	left = right;
//	right = temp;
//}
//void Swap(double& left, double& right) 
//{
//	double temp = left;
//	left = right;
//	right = temp;
//}
//void Swap(char& left, char& right)
//{
//	char temp = left;
//	left = right;
//	right = temp;
//}


//模板
//泛型编程——不再针对某种类型，而是能适应广泛的类型
//函数模板格式
//template<typename T1, typename T2, ......, typename Tn>
//typename是用来定义模板参数关键字，
//也可以使用class(切记：不能使用struct代替class)


////模板
////template<class T>
//template<typename T>
//void Swap(T& left, T& right)
//{
//	T temp = left;
//	left = right;
//	right = temp;
//}
//int main()
//{
//	int a = 10, b = 20;
//	double c = 2.7, d = 3.2;
//	Swap(a, b);
//	Swap(c,d);
//	cout << "a=" << a << "," << "b=" << b << endl;
//	cout << "c=" << c << "," << "d=" << d << endl;
//
//	return 0;
//}


//例如:在C语言中用typedef实现的栈的结构体
//int型栈只能存int型数值，double型栈只能存double型值
//若需要一个栈，既可以存int型，也可以存double型
//在C++中，使用类模板

////类模板
//#include<cassert>
//template<class T>
//class Stack
//{
//public:
//	Stack(int capacity = 10)
//		:_a(new T[capacity])
//		, _capacity(capacity)
//		, _top(0)
//	{}
//	~Stack()
//	{
//		delete[] _a;
//		_capacity = 0;
//		_top = 0;
//	}
//	void Push(const T& x) //传引用，深拷贝
//	{}
//private:
//	T* _a;
//	T _top;
//	T _capacity;
//};
//int main()
//{
//					   //函数模板是去推导其传的类型
//	Stack<int> st1;    //类模板是指定类型
//	st1.Push(1);
//	Stack<double> st2; 
//	st2.Push(2.1);
//	return 0;
//}


//// 动态顺序表
//// 注意：Vector不是具体的类，是编译器根据被实例化的类型生成具体类的模具
//template<class T>
//class Vector
//{
//public:
//	Vector(size_t capacity = 10)
//		: _pData(new T[capacity])
//		, _size(0)
//		, _capacity(capacity)
//	{}
//	// 使用析构函数演示：在类中声明，在类外定义。
//	~Vector();
//	void PushBack(const T& data)；
//		void PopBack()；
//		// ...
//		size_t Size() 
//	{
//		return _size;
//	}
//	T& operator[](size_t pos)
//	{
//		assert(pos < _size);
//		return _pData[pos];
//	}
//private: T* _pData;
//	   size_t _size;
//	   size_t _capacity;
//};
//// 注意：类模板中函数放在类外进行定义时，需要加模板参数列表
//template <class T>
//Vector<T>::~Vector()
//{
//	if (_pData)
//		delete[] _pData;
//	_size = _capacity = 0;
//}

////函数模板不能推演举例：
//template<class T>
//T* func(int n)
//{
//	return new T[n];
//}
//
//int main()
//{
//	
//	int* p1 = func(10);
//	return 0;
//}

////函数模板不能推演举例：
////手动显式实例化
//template<class T>
//T* func(int n)
//{
//	return new T[n];
//}
//
//int main()
//{
//
//	//int* p1 = func(10);
//	//函数模板显式实例化，指定模板参数
//	int* p1 = func<int>(10);
//	double* p2 = func<double>(20);
//
//	return 0;
//}

////函数模板不能推演举例：
////手动显式实例化
////模板参数的很多用法和函数参数是很像的
////模板参数——传递的是类型
////函数参数——传递的是对象值
//template<class T=char>   
//T* func(int n)
//{
//	return new T[n];
//}
//
//int main()
//{
//
//	//int* p1 = func(10);
//	//函数模板显式实例化，指定模板参数
//	int* p1 = func<int>(10);
//	double* p2 = func<double>(20);
//	char* p3 = func(30);
//	return 0;
//}



////函数模板声明、定义分离
////声明
//template<typename T>
//void Swap(T& left, T& right);
//
//
////定义
//template<typename T>
//void Swap(T& left, T& right)
//{
//	T temp = left;
//	left = right;
//	right = temp;
//}


////类模板声明、定义分离
////声明
//template<class T>
//class Vector
//{
//public:
//	Vector(size_t capacity = 10)
//		: _pData(new T[capacity])
//		, _size(0)
//		, _capacity(capacity)
//	{}
//	// 使用析构函数演示：在类中声明，在类外定义。
//	~Vector();
//	void PushBack(const T& data)；
//		void PopBack()；
//		// ...
//		size_t Size()
//	{
//		return _size;
//	}
//	T& operator[](size_t pos)
//	{
//		assert(pos < _size);
//		return _pData[pos];
//	}
//private: T* _pData;
//	   size_t _size;
//	   size_t _capacity;
//};
////类外定义
//template <class T>
//Vector<T>::~Vector()  //指定类域
//{
//	if (_pData)
//		delete[] _pData;
//	_size = _capacity = 0;
//}
//
////模板不支持声明和定义分到两个文件中，会出现链接错误


//template<class T> 
//T Add(const T& left, const T& right)
//{
//	return left + right;
//}
//int main()
//{
//	int a1 = 10, a2 = 20;
//	double d1 = 10.0, d2 = 20.0;
//	Add(a1, a2);    //调用同类型
//	Add(d1, d2);    //调用同类型
//	//Add(a1, d1);  //调用不同类型
//	/*
//	    该语句不能通过编译，因为在编译期间，当编译器看到该实例化时，需要推演其实参类型
//	    通过实参a1将T推演为int，通过实参d1将T推演为double类型，但模板参数列表中只有
//        一个T，编译器无法确定此处到底该将T确定为int 或者 double类型而报错
//	    注意：在模板中，编译器一般不会进行类型转换操作，因为一旦转化出问题，编译器就需要背黑锅
//	    Add(a1, d1);*/
//
//	// 此时有两种处理方式：1. 用户自己来强制转化 2. 使用显式实例化
//	//1.隐式类型转换
//	Add<int>(a1, (int)d1);
//	Add<double>(a1, (int)d1);
//	//2.使用显式实例化
//	Add(a1, (int)d1);
//	Add((double)a1, d1);
//
//	return 0;
//}

// // 专门处理int的加法函数
//int Add(int left, int right)
//{
//    return left + right;
//}
//
//// 通用加法函数
//template<class T>
//T Add(T left, T right)
//{
//    return left + right;
//}
//
//int main()
//{
//    Add(1, 2);       //与非模板函数匹配，编译器不需要特化
//    Add<int>(1, 2);  //调用编译器特化的Add版本
//    return 0;
//}


//// 专门处理int的加法函数
//int Add(int left, int right)
//{
//	return left + right;
//}
//
//// 通用加法函数
//template<class T1, class T2>
//T1 Add(T1 left, T2 right)
//{
//	return left + right;
//}
//
//void Test()
//{
//	Add(1, 2);   // 与非函数模板类型完全匹配，不需要函数模板实例化
//	Add(1, 2.0); // 模板函数可以生成更加匹配的版本，编译器根据实参生成更加匹配的Add函数
//}


////多模板参数
//template<class K,class V>
//void Func(const K& key, const V& value)
//{
//	cout << key << ":" << value << endl;
//}
//
//int main()
//{
//	Func(1, 2);
//	Func(3, 4.9);
//	return 0;
//}

////多模板参数
//template<class K, class V>
//void Func(const K& key, const V& value)
//{
//	cout << key << ":" << value << endl;
//}
//
//int main()
//{
//	Func(1, 2);
//	Func(3, 4.9);
//	Func<int>(3, 4.9);
//	Func<int, int>(3, 4.9);
//	Func<double, double>(3, 4.9);
//
//	Func(5, 'A');
//	Func<int,int>(5, 'A');
//	Func<int, char>(5, 'A');
//
//	return 0;
//}

////多模板参数缺省
////半缺省，注意顺序：从右往左缺省
//template<class K, class V=char>
//void Func()
//{
//	cout << sizeof(K) << endl;
//	cout << sizeof(V) << endl;
//}
//int main()
//{
//	Func<int, int>();
//	Func<int>();
//	return 0;
//}


////多模板参数缺省
////全缺省
//template<class K=char, class V = char>
//void Func()
//{
//	cout << sizeof(K) << endl;
//	cout << sizeof(V) << endl;
//}
//int main()
//{
//	Func<int, int>();
//	Func<int>();
//	Func();
//	return 0;
//}

////多模板参数缺省
//template<class K = int, class V=int >
//void Func()
//{
//	cout << sizeof(K) << endl;
//	cout << sizeof(V) << endl;
//}
//int main()
//{
//	Func<char,char>();
//	Func<int>();
//	Func();
//	return 0;
//}
//
//void Teststring()
//{
//	string s1;				// 构造空的string类对象s1
//	string s2("hello bit"); // 用C格式字符串构造string类对象s2
//	string s3(s2);			// 拷贝构造s3 
//}